package com.oyjd.framework.ui.listview;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import android.content.Context;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.oyjd.R;

/**
 * ListView，封装了下拉刷新和动态加载数据的功能
 * 
 * @author 欧建东
 * @email oyjd@163.com
 * 
 */
public class ListViewEx extends ListView {
	/**
	 * 设置圆形进度条的颜色状态 true--默认颜色 (适合黑底) false-反转颜色（适合白底）
	 */
	public static boolean ProgressBarFlag = true;
	public static int DEFAULT_PAGE_SIZE = 20;// 设置页面大小

	private int pageSize = DEFAULT_PAGE_SIZE;

	private ListHeadView headView;// 列表头视图
	private ListFootView footView;// 列表尾视图
	private int headViewHeight;// 头视图高度

	private List<View> views = new ArrayList<View>();// 子视图
	private ListViewInnerAdapter adapter = new ListViewInnerAdapter();// 列表适配器

	private boolean autoMore = false;// 尾视图：移动到尾部是否自动加载更多

	private int lastDataSize = -1;// 尾视图：最后的数据大小，为【更多数据】是否显示用
	private ListViewExListener listener;// 刷新或加载更多的监听器
	private boolean isInHead = false;// 是否进入头视图
	private int beginY;// 头视图:记录进入头视图的启动Y点
	private boolean signFlag = false;// 头视图:是否记录启动Y点的标志

	private static final int STATUS_PULLDOWN_REFRESH = 1;// 显示下拉刷新状态
	private static final int STATUS_RELEASE_REFRESH = 2;// 显示松开刷新状态
	private static final int STATUS_REFRESHING = 3;// 正在刷新状态
	private static final int STATUS_NONE = 4;// 头视图隐藏状态

	private int currentStatus = STATUS_NONE;// 当前状态

	/**
	 * 构造函数
	 * 
	 * @param context
	 */
	public ListViewEx(Context context) {
		super(context);
		initalize();
	}

	/**
	 * 构造函数
	 * 
	 * @param context
	 */
	public ListViewEx(Context context, AttributeSet attrs) {
		super(context, attrs);
		initalize();
	}

	/**
	 * 构造函数
	 * 
	 * @param context
	 */
	public ListViewEx(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initalize();
	}

	/**
	 * 初始化加载头视图和尾视图以及Listview添加相关监听
	 * 
	 */
	private void initalize() {
		// 添加列表头视图
		this.headView = new ListHeadView(this.getContext());
		measureView(this.headView);
		headViewHeight = headView.getMeasuredHeight();
		this.addHeaderView(this.headView, null, false);
		headView.setPadding(0, -1 * headViewHeight, 0, 0);

		// 添加列表尾视图
		this.footView = new ListFootView(this.getContext());
		this.footView.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				loadNextPage();
			}
		});
		this.addFooterView(this.footView);

		// 列表视图初始化
		this.setSelected(false);
		this.setVerticalFadingEdgeEnabled(false);
		this.setHorizontalFadingEdgeEnabled(false);
		this.setCacheColorHint(0);
		this.setAdapter(adapter);
		this.invalidate();
	}

	/**
	 * 设置页面大小
	 * 
	 * @param pageSize
	 */
	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	/**
	 * 滚动监听
	 */
	private OnScrollListener onScrollListener = new OnScrollListener() {
		@Override
		public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
			isInHead = 0 == firstVisibleItem;
			ListViewEx.this.setVerticalScrollBarEnabled(!isInHead);
		}

		@Override
		public void onScrollStateChanged(AbsListView view, int scrollState) {
			// 自动加载下一页数据
			if (autoMore && footView.getVisibility() == View.VISIBLE && OnScrollListener.SCROLL_STATE_IDLE == scrollState && view.getLastVisiblePosition() == (view.getCount() - 1)) {
				loadNextPage();
			}

		}
	};

	/**
	 * 手势监听
	 */
	private OnTouchListener onTouchListener = new OnTouchListener() {

		@Override
		public boolean onTouch(View v, MotionEvent event) {
			if (isInHead) {// 进入头视图
				int tmpY = (int) event.getY();
				int moveY;
				switch (event.getAction()) {
				case MotionEvent.ACTION_MOVE:
					if (!signFlag) {
						signFlag = true;
						beginY = tmpY;
					}
					moveY = tmpY - beginY;

					if (moveY <= 0 && currentStatus != STATUS_NONE) {// 上推到顶部
						currentStatus = STATUS_NONE;
						headView.setPadding(0, -headViewHeight, 0, 0);
						headView.setStatus(currentStatus);
					} else if (moveY <= headViewHeight) {// 下拉但没超过头视图高
						setSelection(0);
						currentStatus = STATUS_PULLDOWN_REFRESH;
						headView.setPadding(0, moveY - headViewHeight, 0, 0);
						headView.setStatus(currentStatus);
					} else if (moveY > headViewHeight) {// 下拉超过头视图高度
						setSelection(0);
						currentStatus = STATUS_RELEASE_REFRESH;
						headView.setPadding(0, moveY - headViewHeight, 0, 0);
						headView.setStatus(currentStatus);
					}
					break;
				case MotionEvent.ACTION_UP:
					moveY = tmpY - beginY;
					if (moveY <= 0) {// 上推到顶部
						currentStatus = STATUS_NONE;
						headView.setPadding(0, -headViewHeight, 0, 0);
						headView.setStatus(currentStatus);
					} else if (moveY <= headViewHeight) {// 下拉但没超过头视图高
						currentStatus = STATUS_NONE;
						headView.setPadding(0, -headViewHeight, 0, 0);
						headView.setStatus(currentStatus);
					} else if (moveY > headViewHeight) {// 超过头视图高度
						currentStatus = STATUS_REFRESHING;
						headView.setPadding(0, 0, 0, 0);
						headView.setStatus(currentStatus);
						listener.onRefreshClick();
					}
					signFlag = false;
					break;
				case MotionEvent.ACTION_DOWN:
					if (!signFlag) {
						signFlag = true;
						beginY = tmpY;
					}
					break;
				default:
					break;
				}
			}
			return false;
		}

	};

	/**
	 * 获取子视图集合（用来增删查改子视图）
	 * 
	 * @return
	 */
	public List<View> getViews() {
		return views;
	}

	/**
	 * 设置移动到尾部是否自动加载更多
	 * 
	 * @param autoMore
	 */
	public void setAutoMore(boolean autoMore) {
		this.autoMore = autoMore;
	}

	/**
	 * 加载下一页
	 */
	private void loadNextPage() {
		lastDataSize = views.size();
		footView.setStatus(ListFootView.STATUS_LOADING);
		listener.onMoreClick();
	}

	/**
	 * 设置刷新和更多的监听
	 * 
	 * @param listener
	 */
	public void setOnListViewExListener(ListViewExListener listener) {
		if (null != listener) {
			this.listener = listener;
			this.setOnTouchListener(onTouchListener);
			this.setOnScrollListener(onScrollListener);
		}
	}

	/**
	 * 【刷新】操作结束
	 */
	public void notifyRefreshFinished() {
		adapter.notifyDataSetChanged();
		currentStatus = STATUS_NONE;
		headView.setPadding(0, -1 * headViewHeight, 0, 0);
		headView.setStatus(currentStatus);
		invalidate();
		setSelection(1);
		if (views.size() != 0 && views.size() % pageSize == 0) {
			footView.setStatus(ListFootView.STATUS_SHOW_MORE);
		} else {
			footView.setStatus(ListFootView.STATUS_HIDDEN);
		}
	}

	/**
	 * 【更多】操作结束
	 */
	public void notifyMoreFinished() {
		adapter.notifyDataSetChanged();
		if (views.size() != 0 && views.size() != lastDataSize && views.size() % pageSize == 0) {
			footView.setStatus(ListFootView.STATUS_SHOW_MORE);
		} else {
			footView.setStatus(ListFootView.STATUS_HIDDEN);
		}
		lastDataSize = views.size();
	}

	/**
	 * 特殊列表手工设置【更多】是否可见
	 * 
	 * @param visiable
	 *            true-可见 false-不可见
	 */
	public void setFootViewVisiable(boolean visiable) {
		footView.setStatus(visiable ? ListFootView.STATUS_SHOW_MORE : ListFootView.STATUS_HIDDEN);
	}

	/**
	 * ListViewEx监听器
	 * 
	 * @author 欧建东
	 * @email oyjd@163.com
	 * 
	 */
	public interface ListViewExListener {
		/**
		 * 点击刷新事件
		 */
		void onRefreshClick();

		/**
		 * 点击更多数据事件
		 */
		void onMoreClick();
	}

	/**
	 * 内部自定义适配器
	 * 
	 * @author 欧建东
	 * @email oyjd@163.com
	 * 
	 */
	private class ListViewInnerAdapter extends BaseAdapter {

		public int getCount() {
			return views.size();
		}

		public Object getItem(int position) {
			return views.get(position).getTag();
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			return views.get(position);
		}
	}

	// 调整child的width以及height
	private void measureView(View child) {
		ViewGroup.LayoutParams p = child.getLayoutParams();
		if (p == null) {
			p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
		}
		int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
		int lpHeight = p.height;
		int childHeightSpec;
		if (lpHeight > 0) {
			childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
		} else {
			childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
		}
		child.measure(childWidthSpec, childHeightSpec);
	}

	/**
	 * ListView头视图
	 * 
	 * @author 欧建东
	 * @email oyjd@163.com
	 * 
	 */
	private class ListHeadView extends LinearLayout {
		private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);// 格式化更新时间格式

		private ProgressBar mProgressBar;// 进度条
		private ImageView mImage;// 箭头
		private TextView mTipContent;// 信息显示
		private TextView mTime;// 更新时间显示

		private RotateAnimation mFlipAnimation;
		private RotateAnimation mReverseFlipAnimation;
		private boolean arrowDownFlag = true;

		/**
		 * 构造函数
		 * 
		 * @param context
		 */
		public ListHeadView(Context context) {
			super(context);

			mFlipAnimation = new RotateAnimation(0, 180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
			mFlipAnimation.setInterpolator(new LinearInterpolator());
			mFlipAnimation.setDuration(250);
			mFlipAnimation.setFillAfter(true);

			mReverseFlipAnimation = new RotateAnimation(180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
			mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
			mReverseFlipAnimation.setDuration(250);
			mReverseFlipAnimation.setFillAfter(true);

			this.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, ListView.LayoutParams.WRAP_CONTENT));
			this.setGravity(Gravity.CENTER);

			// 内置大的RelativeLayout
			RelativeLayout rl = new RelativeLayout(context);
			this.addView(rl, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));

			// 内置容器设置,包含【信息显示】【更新时间显示】的容器
			LinearLayout tLayout = new LinearLayout(context);
			tLayout.setGravity(Gravity.CENTER);
			tLayout.setOrientation(LinearLayout.VERTICAL);

			LinearLayout.LayoutParams txtLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
			// 添加提示信息
			mTipContent = new TextView(context);
			mTipContent.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
			mTipContent.setText("下拉可以刷新");
			tLayout.addView(mTipContent, txtLayoutParams);

			// 添加更新时间
			mTime = new TextView(context);
			mTime.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
			mTime.setText("更新于：" + sdf.format(System.currentTimeMillis()));
			tLayout.addView(mTime, txtLayoutParams);

			RelativeLayout.LayoutParams mTLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
			mTLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
			rl.addView(tLayout, mTLayoutParams);

			// 内置容器设置,包含圆形进度条和箭头
			FrameLayout fl = new FrameLayout(context);
			fl.setPadding(10, 10, 10, 10);
			FrameLayout.LayoutParams fllp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
			fllp.gravity = Gravity.CENTER;
			// 添加一个圆型进度条
			if (ProgressBarFlag) {
				mProgressBar = new ProgressBar(context);
			} else {
				LayoutInflater flater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				mProgressBar = (ProgressBar) flater.inflate(R.layout.inner_progress, null);
			}
			mProgressBar.setIndeterminate(true);
			fl.addView(mProgressBar, fllp);

			// 添加一个箭头
			mImage = new ImageView(context);
			mImage.setImageResource(R.drawable.arrow);
			fl.addView(mImage, fllp);

			RelativeLayout.LayoutParams flLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
			flLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
			flLayoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
			rl.addView(fl, flLayoutParams);
		}

		/**
		 * 设置状态
		 * 
		 * @param status
		 */
		public void setStatus(int status) {
			switch (status) {
			case ListViewEx.STATUS_NONE:

			case ListViewEx.STATUS_PULLDOWN_REFRESH:
				mProgressBar.setVisibility(View.INVISIBLE);
				mImage.setVisibility(View.VISIBLE);
				if (!arrowDownFlag) {
					arrowDownFlag = true;
					mImage.clearAnimation();
					mImage.startAnimation(mReverseFlipAnimation);
				}
				mTipContent.setText("下拉可以刷新");
				break;
			case ListViewEx.STATUS_RELEASE_REFRESH:
				mProgressBar.setVisibility(View.INVISIBLE);
				mImage.setVisibility(View.VISIBLE);
				if (arrowDownFlag) {
					arrowDownFlag = false;
					mImage.clearAnimation();
					mImage.startAnimation(mFlipAnimation);
				}
				mTipContent.setText("松开可以刷新");
				break;
			case ListViewEx.STATUS_REFRESHING:
				mImage.clearAnimation();
				mImage.setVisibility(View.INVISIBLE);
				mProgressBar.setVisibility(View.VISIBLE);
				mTipContent.setText("正在刷新中...");
				mTime.setText("更新于：" + sdf.format(System.currentTimeMillis()));
				break;
			default:
				break;
			}
		}

	}

	/**
	 * ListView尾视图
	 * 
	 * @author 欧建东
	 * @email oyjd@163.com
	 * 
	 */
	private class ListFootView extends LinearLayout {

		private ProgressBar mProgressBar;// 进度条
		private TextView mTipContent;// 信息提示

		public static final int STATUS_LOADING = 1;// 显示加载状态
		public static final int STATUS_SHOW_MORE = 2;// 显示更多状态
		public static final int STATUS_HIDDEN = 3;// 显示隐藏状态

		/**
		 * 构造函数
		 * 
		 * @param context
		 */
		public ListFootView(Context context) {
			super(context);
			this.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, ListView.LayoutParams.WRAP_CONTENT));
			this.setGravity(Gravity.CENTER);

			// 内置大的RelativeLayout
			RelativeLayout rl = new RelativeLayout(context);
			this.addView(rl, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));

			// 内置容器设置,包含【信息显示】【更新时间显示】的容器
			LinearLayout tLayout = new LinearLayout(context);
			tLayout.setGravity(Gravity.CENTER);
			tLayout.setOrientation(LinearLayout.VERTICAL);

			LinearLayout.LayoutParams txtLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
			// 添加提示信息
			mTipContent = new TextView(context);
			mTipContent.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 22);
			mTipContent.setPadding(0, 10, 0, 0);
			tLayout.addView(mTipContent, txtLayoutParams);

			RelativeLayout.LayoutParams mTLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
			mTLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
			rl.addView(tLayout, mTLayoutParams);

			// 内置容器设置,包含圆形进度条和箭头
			FrameLayout fl = new FrameLayout(context);
			fl.setPadding(10, 10, 10, 10);
			FrameLayout.LayoutParams fllp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
			fllp.gravity = Gravity.CENTER;

			// 添加一个圆型进度条
			if (ProgressBarFlag) {
				mProgressBar = new ProgressBar(context);
			} else {
				LayoutInflater flater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				mProgressBar = (ProgressBar) flater.inflate(R.layout.inner_progress, null);
			}
			mProgressBar.setIndeterminate(true);
			fl.addView(mProgressBar, fllp);

			RelativeLayout.LayoutParams flLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
			flLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
			flLayoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
			rl.addView(fl, flLayoutParams);

			setStatus(STATUS_HIDDEN);
		}

		/**
		 * 设置状态
		 * 
		 * @param status
		 */
		public void setStatus(int status) {
			switch (status) {
			case STATUS_LOADING:
				mProgressBar.setVisibility(View.VISIBLE);
				mTipContent.setText("加载中...");
				this.setVisibility(View.VISIBLE);
				break;
			case STATUS_SHOW_MORE:
				mProgressBar.setVisibility(View.INVISIBLE);
				mTipContent.setText("查看更多");
				this.setVisibility(View.VISIBLE);
				break;
			case STATUS_HIDDEN:
				this.setVisibility(View.GONE);
				break;
			default:
				break;
			}
		}

	}

}
